using Engine;
using Engine.Graphics;
using Game;
using Random = Engine.Random;

namespace SCIENEW {
    public class OresBlock : CubeBlock {
        // 定义方块的索引
        public const int Index = 502;

        // 定义材料类型数组
        public readonly Materials[] Mats = [
            Materials.Gold,
            Materials.Silver,
            Materials.Platinum,
            Materials.Lead,
            Materials.Zinc,
            Materials.Stannary,
            Materials.Mercury,
            Materials.Chromium,
            Materials.Titanium,
            Materials.Nickel,
            Materials.Uranium,
            Materials.Phosphorus
        ];

        // 获取方块掉落物
        public override void GetDropValues(SubsystemTerrain subsystemTerrain, int oldValue, int newValue, int toolLevel, List<BlockDropValue> dropValues, out bool showDebris) {
            int data = Terrain.ExtractData(oldValue);

            // 如果工具等级大于3，并且方块有易爆属性，并且随机数满足条件
            if (toolLevel > 3) {
                if (IsExplosion(data)
                    && (new Random().Int() & 3) == 0) {
                    dropValues.Add(new BlockDropValue { Value = oldValue, Count = 1 });
                    showDebris = true;
                    return;
                }
            }
            // 如果工具等级大于2，并且数据值在1到10之间
            if (toolLevel > 2) {
                Materials material = GetMaterial(data);
                if ((new Random().Int() & 0b1111) == 0) {
                    //1/16概率掉落废铁
                    dropValues.Add(new BlockDropValue { Value = ItemsBlockManager.IdMap["ScrapIron"], Count = 1 });
                }
                else {
                    //掉落随机数量矿石
                    int count = new Random().Int(1, 2);
                    int chunkItem = ItemsBlockManager.GetItemIdByMaterial<OreChunkItem>(material);
                    for (int i = 0; i < count; i++) {
                        if (chunkItem != null) dropValues.Add((new BlockDropValue{Value = chunkItem, Count = 1}));
                    }
                    //掉落伴生矿
                    var companionOres = OresDataBase.GetCompanionOres(material);
                    foreach (var companionOre in companionOres) {
                        float random = new Random().Float();
                        if (random < companionOre.Probability) {
                            int companionItem = ItemsBlockManager.GetItemIdByMaterial<OreChunkItem>(companionOre.Ore);
                            dropValues.Add(new BlockDropValue{Value = companionItem, Count = 1});
                        }
                    }
                }
                // 随机掉落经验
                int count2 = new Random().Int(1, 4);
                for (int i = 0; i < count2; i++) {
                    dropValues.Add(new BlockDropValue { Value = ExperienceBlock.Index, Count = 1 });
                }
                showDebris = true;
            }
            showDebris = true;
        }

        // 获取方块挖掘值
        public override BlockPlacementData GetDigValue(SubsystemTerrain subsystemTerrain, ComponentMiner componentMiner, int value, int toolValue, TerrainRaycastResult raycastResult) {
            return new BlockPlacementData {
                Value = IsUnstable(Terrain.ExtractData(value)) ? Terrain.ReplaceData(MagmaBlock.Index, FluidBlock.SetIsTop(FluidBlock.SetLevel(0, 4), toolValue == MagmaBucketBlock.Index)) : 0,
                CellFace = raycastResult.CellFace
            };
        }

        // 获取方块纹理槽
        public override int GetFaceTextureSlot(int face, int value) {
            Materials material = GetMaterial(Terrain.ExtractData(value));
            int index = Mats.FirstIndex(material);
            return index + 244;
        }

        // 获取方块显示名称
        public override string GetDisplayName(SubsystemTerrain subsystemTerrain, int value) {
            int data = Terrain.ExtractData(value);
            string name = string.Empty;
            if (IsUnstable(data)) name += LanguageControl.Get("Ores", "Unstable");// 检查不稳定状态
            if (IsExplosion(data)) name += LanguageControl.Get("Ores", "Explodable");// 检查易爆状态
            Materials material = GetMaterial(data);
            name += material.ToDisplayName() + LanguageControl.Get("Ores", "Ore");// 获取材料名称并添加后缀
            return name;
        }

        // 获取方块爆炸压力
        public override float GetExplosionPressure(int value) {
            return IsExplosion(Terrain.ExtractData(value)) ? 10f : base.GetExplosionPressure(value);
        }

        // 绘制方块
        public override void DrawBlock(PrimitivesRenderer3D primitivesRenderer, int value, Color color, float size, ref Matrix matrix, DrawBlockEnvironmentData environmentData) {
            BlocksManager.DrawCubeBlock(
                primitivesRenderer,
                value,
                new Vector3(size),
                ref matrix,
                color,
                color,
                environmentData,
                IndustrialModLoader.IETexture
            );
        }

        // 生成方块的地形顶点
        public override void GenerateTerrainVertices(BlockGeometryGenerator generator, TerrainGeometry geometry, int value, int x, int y, int z) {
            generator.GenerateCubeVertices(
                this,
                value,
                x,
                y,
                z,
                Color.White,
                geometry.GetGeometry(IndustrialModLoader.IETexture).OpaqueSubsetsByFace
            );
        }

        // 获取创意模式下方块的所有可能值
        public override IEnumerable<int> GetCreativeValues() {
            var list = new List<int>();
            for (int i = 0; i < 12; i++) {
                list.Add(SetBlockID(Mats[i], false, false));
            }
            #if false
            for (int i = 0; i < 12; i++) {
                list.Add(SetBlockID(i, true, false));
            }
            for (int i = 0; i < 12; i++) {
                list.Add(SetBlockID(i, false, true));
            }
            for (int i = 0; i < 12; i++) {
                list.Add(SetBlockID(i, true, true));
            }
#endif
            return list;
        }

        public override BlockDebrisParticleSystem CreateDebrisParticleSystem(SubsystemTerrain subsystemTerrain, Vector3 position, int value, float strength) => new (subsystemTerrain, position, 1, 1, Color.White, GetFaceTextureSlot(4, value), IndustrialModLoader.IETexture);

        public bool IsExplosion(int data) => (data & 32768) != 0;

        public bool IsUnstable(int data) => (data & 65536) != 0;

        public Materials GetMaterial(int data) => (Materials)(data & 16383);

        public int GetMatIndex(int data) => data & 16383;

        public static int SetBlockID(Materials material, bool isExplosion, bool isUnstable) {
            int data = (int)material;
            if (isExplosion) data |= 32768;
            if (isUnstable) data |= 65536;
            return Terrain.MakeBlockValue(Index, 0, data);
        }
    }
}

/*
data 位的作用
65536 位（第 16 位）：表示“不稳定”状态。
32768 位（第 15 位）：表示“易爆”状态。
16383 位（前 14 位）：表示方块的基础数据值（1-12）。

位操作的作用
data & 65536：检查方块是否有“不稳定”状态。
data & 32768：检查方块是否有“易爆”状态。
data >> 1 & 16383：获取方块的基础数据值，并右移一位。
data = data >> 1 & 16383：右移一位并且保留基础数据值。
data << 14：将基础数据值左移 14 位，以便与其他状态位进行或操作。

GetCreativeValues 方法的解释
该方法生成创意模式下所有可能的方块值组合，包括基础数据值和不同的状态（如“不稳定”和“易爆”）。通过位操作将基础数据值和状态组合在一起，生成完整的方块值列表。
*/